package network

import (
	"net"
	"github.com/wanhuo/GoSocketFrame/common"
	"sync"
	"github.com/wanhuo/GoSocketFrame/utils"
	"log"
	"time"
)

const (
	KEEPALIVE_DETECT_TIME = 20 //心跳定时器间隔
	MainCmd_Network_FrameWork = 1000 //框架主命令
	SubCmd_Network_HeartBeat = 1 //心跳命令
)

type NetworkStatus int

const (
	NetworkStatus_Normal    NetworkStatus = 0 //正常
	NetworkStatus_KeepAlive NetworkStatus = 1 //心跳检查
)

type ConnectStatusType int

//心跳状态
const (
	KeepAlive_Dead ConnectStatusType = 0 //死亡连接
	KeepAlive_Warn ConnectStatusType = 1 //危险连接
	KeepAlive_Safe ConnectStatusType = 2 //安全连接
)

type SocketAcceptor struct {
	listener       net.Listener
	running        bool
	sockMap        map[uint64]*Session
	fdcounter      uint64
	iattemper      common.IAttemperEngineSink
	mutex          sync.Mutex
	keepAliveTimer *utils.Timer  //心跳定时器
	log            *utils.Logger //日志句柄
}

func (self *SocketAcceptor) Start(address string, keepAliveStatus NetworkStatus) error {
	ln, err := net.Listen("tcp", address)
	self.sockMap = make(map[uint64]*Session)
	if err != nil {
		return err
	}
	self.listener = ln
	self.running = true

	//与客户端的连接需要心跳 需要加密
	if keepAliveStatus != NetworkStatus_Normal {
		if self.keepAliveTimer == nil {
			self.keepAliveTimer = utils.NewTimer(self, KEEPALIVE_DETECT_TIME*time.Second, 0)
			self.keepAliveTimer.Start(utils.Timer_RunLoop)
		}
	}

	for self.running {
		conn, err := ln.Accept()

		if err != nil {
			log.Println(err)
			continue
		}
		self.mutex.Lock()
		self.fdcounter++
		ses := NewSession(self.fdcounter, conn, self.iattemper)
		self.sockMap[self.fdcounter] = ses
		self.mutex.Unlock()

		self.iattemper.OnEventTCPNetworkLink(ses)
		ses.OnClose = func(mSession common.ISession) {
			self.mutex.Lock()
			delete(self.sockMap, mSession.ID())
			self.mutex.Unlock()
			self.log.Debugf("[关闭连接] ses:%d\n", mSession.ID())
		}
		ses.SetBindData(KeepAlive_Safe)
		self.log.Debugf("[新的连接] ses:%d\n", ses.ID())
	}
	return nil
}

func (self *SocketAcceptor) OnTimer(callback int) {
	var deadSesVec []*Session
	self.mutex.Lock()
	//遍历所有session
	for i := range self.sockMap {
		ses := self.sockMap[i]
		if ses == nil {
			continue
		}
		userData := ses.GetBindData()
		switch status := userData.(type) {
		case ConnectStatusType:
			if status == KeepAlive_Dead {
				deadSesVec = append(deadSesVec, ses)
			} else if status == KeepAlive_Safe {
				status--
				ses.SetBindData(status)
			} else if status == KeepAlive_Warn {
				status--
				ses.SetBindData(status)
				//这里需要加入心跳检测的命令
				ses.Send(MainCmd_Network_FrameWork, SubCmd_Network_HeartBeat, nil)
			}
		}
	}
	self.mutex.Unlock()
	for _, ses := range deadSesVec {
		self.iattemper.OnEventTCPNetworkShut(ses)
		if ses.OnClose != nil {
			ses.OnClose(ses)
		}
	}

}


func (self *SocketAcceptor) Stop() {
	if !self.running {
		return
	}
	self.running = false
	self.listener.Close()
}

func NewAcceptor(attemper common.IAttemperEngineSink) *SocketAcceptor {
	self := &SocketAcceptor{
		iattemper: attemper,
		fdcounter: 0,
		log:       utils.NewLogger(),
	}
	return self
}


